package com.binance.notification.web.service.abnormaltrade.impl;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;

import com.binance.notification.web.service.abnormaltrade.integration.PriceService;
import org.apache.commons.lang.StringUtils;
import org.apache.tools.ant.util.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StopWatch;

import com.binance.notification.web.service.abnormaltrade.IAbnormalTradeNoticeLogService;
import com.binance.notification.web.service.abnormaltrade.IAbnormalTradePushNoticeService;
import com.binance.notification.web.service.abnormaltrade.IPriceBreakthroughsService;
import com.binance.notification.web.service.abnormaltrade.convert.PriceBreakthoughsPushMessageConvertor;
import com.binance.notification.web.service.abnormaltrade.enums.AbnormalTradePushNoticeBusTypeEnum;
import com.binance.notification.web.service.abnormaltrade.enums.AbnromalTradeBusinessTypeEnum;
import com.binance.notification.web.service.abnormaltrade.enums.AbnromalTradeNoticeDescEnum;
import com.binance.notification.web.service.abnormaltrade.enums.AggregationTypeEnum;
import com.binance.notification.web.service.abnormaltrade.enums.IntervalEnum;
import com.binance.notification.web.service.abnormaltrade.integration.ExchangeProductService;
import com.binance.notification.web.service.abnormaltrade.integration.KlineService;
import com.binance.notification.web.service.abnormaltrade.log.LoggerUtils;
import com.binance.notification.web.service.abnormaltrade.models.AbnormalTradeNoticeLogBo;
import com.binance.notification.web.service.abnormaltrade.models.KlineInfo;
import com.binance.notification.web.utils.Worker;
import com.binance.sysconf.service.SysConfigVarCacheService;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import io.shardingsphere.api.HintManager;

@Service
public class PriceBreakthroughsServiceImpl implements IPriceBreakthroughsService {
    private static final org.slf4j.Logger log = LoggerUtils.getLogger(PriceBreakthroughsServiceImpl.class);
    @Autowired
    private KlineService klineService;
    @Autowired
    private ExchangeProductService exchangeProductService;
    @Autowired
    private IAbnormalTradeNoticeLogService abnormalTradeNoticeLogService;
    @Autowired
    private SysConfigVarCacheService sysConfigService;
    @Autowired
    private IAbnormalTradePushNoticeService abnormalTradePushNoticeService;
    @Autowired
    private PriceService priceService;
    @Autowired
    private Worker worker;

    /**
     * 监听交易对列表并且入库
     * 
     * @throws Exception
     */
    @Override
    public void monitorSymbolListAndStore(IntervalEnum intervalEnum, Integer klineSize,
            AggregationTypeEnum aggregationTypeEnum) throws Exception {
        List<String> symbolLists = exchangeProductService.getUsdtAndBtcSymbolList();
        log.info("PriceBreakthroughsServiceImpl.monitorSymbolListAndStore symbolLists={}", symbolLists);
        for (String symbol : symbolLists) {
            worker.submit(() -> {
                HintManager hintManager = null;
                try {
                    // 判断是否有监控数据
                    StopWatch stopWatch = new StopWatch();
                    stopWatch.start();
                    AbnormalTradeNoticeLogBo abnormalTradeNoticeLogBo = monitorPriceBreakthroughsEvent(symbol,
                            splitQuoteAssetName(symbol), intervalEnum, klineSize, aggregationTypeEnum);
                    stopWatch.stop();
                    log.info("PriceBreakthroughsServiceImpl.monitorPriceBreakthroughsEvent symbol={}, elapsedTime={}",
                            symbol, stopWatch.getTotalTimeSeconds());
                    if (null != abnormalTradeNoticeLogBo) {
                        List<AbnormalTradeNoticeLogBo> abnormalTradeNoticeLogBoList = Lists.newArrayList();
                        // 强制路由主库
                        hintManager = HintManager.getInstance();
                        hintManager.setMasterRouteOnly();
                        AbnormalTradeNoticeLogBo queryResult = abnormalTradeNoticeLogService
                                .findBySymbolAndBusinessTypeAndDescCode(abnormalTradeNoticeLogBo.getSymbol(),
                                        abnormalTradeNoticeLogBo.getBusinessType().name(),
                                        abnormalTradeNoticeLogBo.getDescCode().getDescCode());
                        log.info("PriceBreakthroughsServiceImpl.pushAbnormalTradeNotice symbol={}, queryResult={}",
                                symbol, queryResult);
                        if (null != queryResult) {
                            abnormalTradeNoticeLogBoList.add(queryResult);
                            String content =
                                    PriceBreakthoughsPushMessageConvertor.wrapMessage(abnormalTradeNoticeLogBoList);
                            abnormalTradePushNoticeService.pushWebMessage(AbnormalTradePushNoticeBusTypeEnum.PB, " ",
                                    content);
                            log.info("PriceBreakthroughsServiceImpl.pushAbnormalTradeNotice symbol={}, content={}",
                                    symbol, content);
                        }
                    }
                } catch (Exception e) {
                    log.error("PriceBreakthroughsServiceImpl.monitorSymbolListAndStore Exception symbol=" + symbol, e);
                } finally {
                    if (null != hintManager) {
                        hintManager.close();
                    }
                }
            });
        }
    }

    private String splitQuoteAssetName(String symbol) {
        if (symbol.endsWith("BTC")) {
            return "BTC";
        }
        if (symbol.endsWith("USDT")) {
            return "USDT";
        }
        throw new IllegalArgumentException("illegal symbol=" + symbol);
    }

    /**
     * 判断是否是重复事件
     */
    private Boolean isDuplicateEventLog(String symbol, AbnormalTradeNoticeLogBo after) {
        log.info("PriceBreakthroughsServiceImpl.isDuplicateEventLog symbol={},after={}", symbol, after);
        if (null == after) {
            return Boolean.FALSE;
        }
        // 尝试从数据库中获取历史记录
        AbnormalTradeNoticeLogBo before = abnormalTradeNoticeLogService.findBySymbolAndBusinessTypeAndDescCode(symbol,
                AbnromalTradeBusinessTypeEnum.PriceBreakthroughs.name(), after.getDescCode().getDescCode());
        if (null == before) {
            return Boolean.FALSE;
        }
        log.info("PriceBreakthroughsServiceImpl.isDuplicateEventLog symbol={},before={}", symbol, before);
        Long diffTime = new Date().getTime() - before.getCreatedTime().getTime();
        Long fifteenMinute = 1000 * 60 * 15L;
        Long oneHour = 1000 * 60 * 60L;
        Long oneDay = 1000 * 60 * 60 * 24L;
        log.info("PriceBreakthroughsServiceImpl.isDuplicateEventLog symbol={},diffTime={}", symbol, diffTime);
        if (AbnromalTradeNoticeDescEnum.PriceBreakthroughs_New_High_Daily == after.getDescCode()
                && diffTime.compareTo(fifteenMinute) >= 0) {
            return Boolean.FALSE;
        }
        if (AbnromalTradeNoticeDescEnum.PriceBreakthroughs_New_Low_Daily == after.getDescCode()
                && diffTime.compareTo(fifteenMinute) >= 0) {
            return Boolean.FALSE;

        }
        if (AbnromalTradeNoticeDescEnum.PriceBreakthroughs_New_High_Weekly == after.getDescCode()
                && diffTime.compareTo(oneHour) >= 0) {
            return Boolean.FALSE;

        }
        if (AbnromalTradeNoticeDescEnum.PriceBreakthroughs_New_Low_Weekly == after.getDescCode()
                && diffTime.compareTo(oneHour) >= 0) {
            return Boolean.FALSE;

        }
        if (AbnromalTradeNoticeDescEnum.PriceBreakthroughs_New_High_Monthly == after.getDescCode()
                && diffTime.compareTo(oneDay) >= 0) {
            return Boolean.FALSE;

        }
        if (AbnromalTradeNoticeDescEnum.PriceBreakthroughs_New_Low_Monthly == after.getDescCode()
                && diffTime.compareTo(oneDay) >= 0) {
            return Boolean.FALSE;

        }
        return Boolean.TRUE;
    }


    /**
     * 判断是否小幅度波动,比如24h涨跌幅小于5%这种不应该统计进去
     */
    private Boolean isSmallFluctuation(String symbol, AbnormalTradeNoticeLogBo after) {
        log.info("PriceBreakthroughsServiceImpl.isSmallFluctuation symbol={},after={}", symbol, after);
        if (after.getDescCode() == AbnromalTradeNoticeDescEnum.PriceBreakthroughs_New_High_Daily ||
                after.getDescCode() == AbnromalTradeNoticeDescEnum.PriceBreakthroughs_New_Low_Daily) {
            if (StringUtils.isNotBlank(after.getBusinessData().get("priceChangePercent"))) {
                MathContext mc = new MathContext(8, RoundingMode.HALF_UP);
                BigDecimal absPriceChangePercent = new BigDecimal(after.getBusinessData().get("priceChangePercent")).abs(mc);
                log.info("PriceBreakthroughsServiceImpl.isSmallFluctuation.finalresult,symbol={},priceChangePercent={},absPriceChangePercent={}",
                        symbol, after.getBusinessData().get("priceChangePercent"), absPriceChangePercent);
                if (absPriceChangePercent.compareTo(new BigDecimal("0.05")) >= 0) {
                    return Boolean.FALSE;
                } else {
                    return Boolean.TRUE;
                }
            }
        }

        if (after.getDescCode() != AbnromalTradeNoticeDescEnum.PriceBreakthroughs_New_High_Daily) {
            return Boolean.FALSE;
        }
        List<KlineInfo> minutesklineInfos = klineService.fetchKline(symbol, 1, IntervalEnum.ONE_MINUTES, null, null);
        if (CollectionUtils.isEmpty(minutesklineInfos) || minutesklineInfos.size() < 1) {
            log.info("PriceBreakthroughsServiceImpl.isSmallFluctuation minutesklineInfos empty symbol={} ", symbol);
            return Boolean.FALSE;
        }
        List<KlineInfo> aggregationInfos = klineService.fetchKline(symbol, 24, IntervalEnum.ONE_HOUR, null, null);
        if (CollectionUtils.isEmpty(aggregationInfos) || aggregationInfos.size() < 24) {
            log.info("PriceBreakthroughsServiceImpl.isSmallFluctuation aggregationInfos empty symbol={} ", symbol);
            return Boolean.FALSE;
        }
        BigDecimal minutesClosePirce = minutesklineInfos.get(0).getClose();// 当前收盘价
        BigDecimal hourClosePriceBeforeDay = aggregationInfos.get(0).getClose();// 24小时前的收盘价
        log.info(
                "PriceBreakthroughsServiceImpl.isSmallFluctuation  symbol={},minutesClosePirce={},hourClosePriceBeforeDay={} ",
                symbol, minutesClosePirce, hourClosePriceBeforeDay);

        if (hourClosePriceBeforeDay.compareTo(BigDecimal.ZERO) <= 0) {
            // 24h小时前的收盘价小于零就放过去算了
            return Boolean.FALSE;
        }
        MathContext mc = new MathContext(8, RoundingMode.HALF_UP);
        BigDecimal diffPrice = minutesClosePirce.subtract(hourClosePriceBeforeDay, mc);
        BigDecimal riseAndFallPercentage = diffPrice.divide(hourClosePriceBeforeDay, mc);
        BigDecimal absRiseAndFallPercentage = riseAndFallPercentage.abs(mc);
        log.info("PriceBreakthroughsServiceImpl.isSmallFluctuation.finalresult symbol={},diffPrice={},riseAndFallPercentage={}",
                symbol, riseAndFallPercentage, absRiseAndFallPercentage);
        if (absRiseAndFallPercentage.compareTo(new BigDecimal("0.05")) >= 0) {
            return Boolean.FALSE;
        } else {
            return Boolean.TRUE;
        }
    }

    /**
     * 监听价格突破事件
     */
    private AbnormalTradeNoticeLogBo monitorPriceBreakthroughsEvent(String symbol, String quoteAssetName,
            IntervalEnum intervalEnum, Integer klineSize, AggregationTypeEnum aggregationTypeEnum) {
        try {
            log.info(
                    "PriceBreakthroughsServiceImpl.monitorPriceBreakthroughsEvent symbol={}, quoteAssetName={}"
                            + ", intervalEnum={}, klineSize={}, aggregationTypeEnum={}",
                    symbol, quoteAssetName, intervalEnum, klineSize, aggregationTypeEnum);
            Boolean eventFlag = Boolean.FALSE;
            if (AggregationTypeEnum.AGGREGATION_MAX == aggregationTypeEnum) {
                eventFlag = aggregationMax(symbol, intervalEnum, klineSize);
            }
            if (AggregationTypeEnum.AGGREGATION_MIN == aggregationTypeEnum) {
                eventFlag = aggregationMin(symbol, intervalEnum, klineSize);
            }
            // 如果没有事件触发，那么直接返回
            log.info("PriceBreakthroughsServiceImpl.monitorPriceBreakthroughsEvent symbol={},eventFlag={}", symbol,
                    eventFlag);
            if (!eventFlag) {
                return null;
            }
            // 如果有事件触发，那么开始对文案进行转义
            AbnromalTradeNoticeDescEnum abnromalTradeNoticeDescEnum =
                    convertDesc(intervalEnum, klineSize, aggregationTypeEnum);
            if (null == abnromalTradeNoticeDescEnum) {
                return null;
            }
            AbnormalTradeNoticeLogBo abnormalTradeNoticeLogBo = new AbnormalTradeNoticeLogBo();
            abnormalTradeNoticeLogBo.setSymbol(symbol);
            abnormalTradeNoticeLogBo.setQuoteAssetName(quoteAssetName);
            abnormalTradeNoticeLogBo.setDescCode(abnromalTradeNoticeDescEnum);
            abnormalTradeNoticeLogBo.setBusinessType(AbnromalTradeBusinessTypeEnum.PriceBreakthroughs);
            Map<String, String> data = Maps.newConcurrentMap();
            data.put("recordTime", formatRecordTimeByAbnromalTradeNoticeDescEnum(abnromalTradeNoticeDescEnum));
            if (AbnromalTradeNoticeDescEnum.PriceBreakthroughs_New_High_Daily == abnromalTradeNoticeDescEnum ||
                    AbnromalTradeNoticeDescEnum.PriceBreakthroughs_New_Low_Daily == abnromalTradeNoticeDescEnum) {
                String priceChangePercent = priceService.getPriceChangePercent(symbol);
                if (StringUtils.isNotBlank(priceChangePercent)) {
                    MathContext mc = new MathContext(8, RoundingMode.HALF_UP);
                    priceChangePercent= String.valueOf(new BigDecimal(priceChangePercent).divide(new BigDecimal(100),mc));
                    data.put("priceChangePercent", priceChangePercent);
                }
            }
            abnormalTradeNoticeLogBo.setBusinessData(data);
            log.info(
                    "PriceBreakthroughsServiceImpl.monitorPriceBreakthroughsEvent symbol={}, AbnormalTradeNoticeLogBo={}",
                    symbol, abnormalTradeNoticeLogBo);
            Boolean isDuplicateEventFlag = isDuplicateEventLog(symbol, abnormalTradeNoticeLogBo);
            Boolean isSmallFluctuationFalg = isSmallFluctuation(symbol, abnormalTradeNoticeLogBo);
            log.info(
                    "PriceBreakthroughsServiceImpl.monitorPriceBreakthroughsEvent symbol={},isDuplicateEventFlag={},isSmallFluctuationFalg={}",
                    symbol, isDuplicateEventFlag, isSmallFluctuationFalg);
            if (isDuplicateEventFlag || isSmallFluctuationFalg) {
                return null;
            }
            abnormalTradeNoticeLogService.addOrUpdateAbnormalTradeNoticeLog(abnormalTradeNoticeLogBo);
            log.info(
                    "PriceBreakthroughsServiceImpl.monitorPriceBreakthroughsEvent symbol={} addOrUpdateAbnormalTradeNoticeLog={}",
                    symbol, abnormalTradeNoticeLogBo);
            return abnormalTradeNoticeLogBo;
        } catch (Exception e) {
            log.error("PriceBreakthroughsServiceImpl.monitorPriceBreakthroughsEvent Exception: ", e);
            return null;
        }
    }

    /**
     * 格式化消息生成的时间，以备不时之需
     */
    private String formatRecordTimeByAbnromalTradeNoticeDescEnum(
            AbnromalTradeNoticeDescEnum abnromalTradeNoticeDescEnum) {
        Date nowDate = new Date();
        String recordTime = DateUtils.format(nowDate, "yyyy-MM-dd");
        if (AbnromalTradeNoticeDescEnum.PriceBreakthroughs_New_High_Daily == abnromalTradeNoticeDescEnum
                || AbnromalTradeNoticeDescEnum.PriceBreakthroughs_New_Low_Daily == abnromalTradeNoticeDescEnum) {
            recordTime = DateUtils.format(nowDate, "yyyy-MM-dd HH:mm:00");
        }
        if (AbnromalTradeNoticeDescEnum.PriceBreakthroughs_New_High_Weekly == abnromalTradeNoticeDescEnum
                || AbnromalTradeNoticeDescEnum.PriceBreakthroughs_New_Low_Weekly == abnromalTradeNoticeDescEnum) {
            recordTime = DateUtils.format(nowDate, "yyyy-MM-dd HH:00:00");
        }
        if (AbnromalTradeNoticeDescEnum.PriceBreakthroughs_New_High_Monthly == abnromalTradeNoticeDescEnum
                || AbnromalTradeNoticeDescEnum.PriceBreakthroughs_New_Low_Monthly == abnromalTradeNoticeDescEnum) {
            recordTime = DateUtils.format(nowDate, "yyyy-MM-dd");
        }
        return recordTime;
    }

    /**
     * 求某个周期内的k线的最大值
     */
    private Boolean aggregationMax(String symbol, IntervalEnum intervalEnum, Integer klineSize) {
        // 拉取1分钟的k线，拉一根
        List<KlineInfo> minutesklineInfos = klineService.fetchKline(symbol, 1, IntervalEnum.ONE_MINUTES, null, null);
        if (CollectionUtils.isEmpty(minutesklineInfos) || minutesklineInfos.size() < 1) {
            log.info("PriceBreakthroughsServiceImpl.aggregationMax klineInfos empty symbol={} ", symbol);
            return Boolean.FALSE;
        }

        List<KlineInfo> aggregationInfos = klineService.fetchKline(symbol, klineSize, intervalEnum, null, null);
        if (CollectionUtils.isEmpty(aggregationInfos) || aggregationInfos.size() < klineSize) {
            log.info("PriceBreakthroughsServiceImpl.aggregationMax klineInfos empty symbol={} ", symbol);
            return Boolean.FALSE;
        }
        List<BigDecimal> highPriceList = Lists.newArrayList();
        List<BigDecimal> lowPriceList = Lists.newArrayList();

        for (KlineInfo klineInfo : aggregationInfos) {
            highPriceList.add(klineInfo.getHigh());
            lowPriceList.add(klineInfo.getLow());
        }
        BigDecimal maxPrice = Collections.max(highPriceList);// 聚合的历史最高价
        BigDecimal minPrice = Collections.min(lowPriceList);// 聚合的历史最低价
        BigDecimal minutesMax = minutesklineInfos.get(0).getHigh();// 1分钟最高价
        BigDecimal minutesMin = minutesklineInfos.get(0).getLow();// 1分钟最低价
        Boolean needSkipFlag = needSkip(maxPrice, minPrice, splitQuoteAssetName(symbol));
        log.info("PriceBreakthroughsServiceImpl.aggregationMax  symbol={},needSkipFlag={} ", symbol, needSkipFlag);
        if (minutesMax.compareTo(maxPrice) >= 0 && !needSkipFlag) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    /**
     * 求某个周期内的k线的最小值
     */
    private Boolean aggregationMin(String symbol, IntervalEnum intervalEnum, Integer klineSize) {
        List<KlineInfo> minutesklineInfos = klineService.fetchKline(symbol, 1, IntervalEnum.ONE_MINUTES, null, null);
        if (CollectionUtils.isEmpty(minutesklineInfos) || minutesklineInfos.size() < 1) {
            log.info("PriceBreakthroughsServiceImpl.aggregationMin klineInfos empty symbol={} ", symbol);
            return Boolean.FALSE;
        }

        List<KlineInfo> aggregationInfos = klineService.fetchKline(symbol, klineSize, intervalEnum, null, null);
        if (CollectionUtils.isEmpty(aggregationInfos) || aggregationInfos.size() < klineSize) {
            log.info("PriceBreakthroughsServiceImpl.aggregationMin klineInfos empty symbol={} ", symbol);
            return Boolean.FALSE;
        }
        List<BigDecimal> highPriceList = Lists.newArrayList();
        List<BigDecimal> lowPriceList = Lists.newArrayList();
        for (KlineInfo klineInfo : aggregationInfos) {
            highPriceList.add(klineInfo.getHigh());
            lowPriceList.add(klineInfo.getLow());
        }
        BigDecimal maxPrice = Collections.max(highPriceList);// 聚合的历史最高价
        BigDecimal minPrice = Collections.min(lowPriceList);// 聚合的历史最低价
        BigDecimal minutesMim = minutesklineInfos.get(0).getLow();// 1分钟最低价
        BigDecimal minutesMax = minutesklineInfos.get(0).getHigh();// 1分钟最低价
        Boolean needSkipFlag = needSkip(maxPrice, minPrice, splitQuoteAssetName(symbol));
        log.info("PriceBreakthroughsServiceImpl.aggregationMin  symbol={},needSkipFlag={} ", symbol, needSkipFlag);
        if (minutesMim.compareTo(minPrice) <= 0 && !needSkipFlag) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    /**
     * 某些归零的币实际上价格差只要小小的波动就会在涨幅上体现很多，这种币要剔除
     */
    public Boolean needSkip(BigDecimal maxPrice, BigDecimal lowPrice, String quoteAssetName) {
        MathContext mc = new MathContext(8, RoundingMode.HALF_UP);
        BigDecimal diffPrice = maxPrice.subtract(lowPrice, mc);
        BigDecimal absDiffPrice = diffPrice.abs(mc);
        if ("BTC".equals(quoteAssetName) && absDiffPrice.compareTo(new BigDecimal("0.00000004")) <= 0) {
            return Boolean.TRUE;
        }
        if ("USDT".equals(quoteAssetName) && absDiffPrice.compareTo(new BigDecimal("0.0004")) <= 0) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    /**
     * 转换相应的文案枚举出来返回给前端
     */
    private AbnromalTradeNoticeDescEnum convertDesc(IntervalEnum intervalEnum, Integer klineSize,
            AggregationTypeEnum aggregationTypeEnum) {
        AbnromalTradeNoticeDescEnum abnromalTradeNoticeDescEnum = null;
        if (IntervalEnum.ONE_HOUR == intervalEnum && klineSize == 24
                && AggregationTypeEnum.AGGREGATION_MAX == aggregationTypeEnum) {
            abnromalTradeNoticeDescEnum = AbnromalTradeNoticeDescEnum.PriceBreakthroughs_New_High_Daily;
        }
        if (IntervalEnum.ONE_DAY == intervalEnum && klineSize == 7
                && AggregationTypeEnum.AGGREGATION_MAX == aggregationTypeEnum) {
            abnromalTradeNoticeDescEnum = AbnromalTradeNoticeDescEnum.PriceBreakthroughs_New_High_Weekly;
        }
        if (IntervalEnum.ONE_DAY == intervalEnum && klineSize == 30
                && AggregationTypeEnum.AGGREGATION_MAX == aggregationTypeEnum) {
            abnromalTradeNoticeDescEnum = AbnromalTradeNoticeDescEnum.PriceBreakthroughs_New_High_Monthly;
        }
        if (IntervalEnum.ONE_HOUR == intervalEnum && klineSize == 24
                && AggregationTypeEnum.AGGREGATION_MIN == aggregationTypeEnum) {
            abnromalTradeNoticeDescEnum = AbnromalTradeNoticeDescEnum.PriceBreakthroughs_New_Low_Daily;
        }
        if (IntervalEnum.ONE_DAY == intervalEnum && klineSize == 7
                && AggregationTypeEnum.AGGREGATION_MIN == aggregationTypeEnum) {
            abnromalTradeNoticeDescEnum = AbnromalTradeNoticeDescEnum.PriceBreakthroughs_New_Low_Weekly;
        }
        if (IntervalEnum.ONE_DAY == intervalEnum && klineSize == 30
                && AggregationTypeEnum.AGGREGATION_MIN == aggregationTypeEnum) {
            abnromalTradeNoticeDescEnum = AbnromalTradeNoticeDescEnum.PriceBreakthroughs_New_Low_Monthly;
        }
        log.info(
                "PriceBreakthroughsServiceImpl.convertDesc intervalEnum={},klineSize={}, aggregationTypeEnum={},AbnromalTradeNoticeDescEnum={}",
                intervalEnum, klineSize, aggregationTypeEnum, abnromalTradeNoticeDescEnum);
        return abnromalTradeNoticeDescEnum;
    }

    // @Override
    // public List<AbnormalTradeNoticeLogBo> getPriceBreakthroughsLogList(Integer page, Integer
    // offset) {
    // List<AbnormalTradeNoticeLogBo> abnormalTradeNoticeLogBoList = abnormalTradeNoticeLogService
    // .findByBusinessType(AbnromalTradeBusinessTypeEnum.PriceBreakthroughs.name(), page, offset);
    // List<AbnormalTradeNoticeLogBo> wrapAbnormalTradeNoticeLogBoList =
    // wrapNeedPushFlag(abnormalTradeNoticeLogBoList);
    // return wrapAbnormalTradeNoticeLogBoList;
    // }

    /**
     * 格式化数据判断是否需要推送
     */
    // @Override
    // public List<AbnormalTradeNoticeLogBo> wrapNeedPushFlag(
    // List<AbnormalTradeNoticeLogBo> abnormalTradeNoticeLogBoList) {
    // List<AbnormalTradeNoticeLogBo> resultList = Lists.newArrayList();
    // log.info("PriceBreakthroughsServiceImpl.wrapNeedPushFlag strat
    // abnormalTradeNoticeLogBoList={}",
    // abnormalTradeNoticeLogBoList);
    // for (AbnormalTradeNoticeLogBo abnormalTradeNoticeLogBo : abnormalTradeNoticeLogBoList) {
    // try {
    // log.info("PriceBreakthroughsServiceImpl.wrapNeedPushFlag abnormalTradeNoticeLogBo={}",
    // abnormalTradeNoticeLogBo);
    // Map<String, String> params = abnormalTradeNoticeLogBo.getBusinessData();
    // // 需要再覆盖一次
    // Boolean pushFlag = convertPushFlag(abnormalTradeNoticeLogBo.getDescCode());
    // params.put("pushFlag", String.valueOf(pushFlag));
    // abnormalTradeNoticeLogBo.setBusinessData(params);
    // log.info("PriceBreakthroughsServiceImpl.wrapNeedPushFlag singlefinish
    // abnormalTradeNoticeLogBo={}",
    // abnormalTradeNoticeLogBo);
    // resultList.add(abnormalTradeNoticeLogBo);
    // } catch (Exception e) {
    // log.error("PriceBreakthroughsServiceImpl.wrapNeedPushFlag Exception=", e);
    // continue;
    // }
    // }
    // log.info("PriceBreakthroughsServiceImpl.wrapNeedPushFlag finish resultList={}", resultList);
    // return resultList;
    // }


    /**
     * 格式化数据判断是否需要推送
     */
    @Override
    public AbnormalTradeNoticeLogBo wrapNeedPushFlag(AbnormalTradeNoticeLogBo abnormalTradeNoticeLogBo) {
        try {
            log.info("PriceBreakthroughsServiceImpl.wrapNeedPushFlag abnormalTradeNoticeLogBo={}",
                    abnormalTradeNoticeLogBo);
            Map<String, String> params = abnormalTradeNoticeLogBo.getBusinessData();
            // 需要再覆盖一次
            Boolean pushFlag = convertPushFlag(abnormalTradeNoticeLogBo.getDescCode());
            params.put("pushFlag", String.valueOf(pushFlag));
            abnormalTradeNoticeLogBo.setBusinessData(params);
            log.info("PriceBreakthroughsServiceImpl.wrapNeedPushFlag singlefinish abnormalTradeNoticeLogBo={}",
                    abnormalTradeNoticeLogBo);
        } catch (Exception e) {
            log.error("PriceBreakthroughsServiceImpl.wrapNeedPushFlag Exception=", e);
        }
        log.info("PriceBreakthroughsServiceImpl.wrapNeedPushFlag finish abnormalTradeNoticeLogBo={}",
                abnormalTradeNoticeLogBo);
        return abnormalTradeNoticeLogBo;
    }


    /**
     * 每个涨跌幅的数据都由不同的开关决定，具体的开关在admin上面，消息管理-》异常价格配置页面
     */
    public Boolean convertPushFlag(AbnromalTradeNoticeDescEnum abnromalTradeNoticeDescEnum) {
        Boolean pushFlag = Boolean.FALSE;
        if (AbnromalTradeNoticeDescEnum.PriceBreakthroughs_New_High_Daily == abnromalTradeNoticeDescEnum) {
            pushFlag = getAbnormalPriceSwitch("new_high_daily_switch");
            return pushFlag;
        }
        if (AbnromalTradeNoticeDescEnum.PriceBreakthroughs_New_High_Weekly == abnromalTradeNoticeDescEnum) {
            pushFlag = getAbnormalPriceSwitch("new_high_weekly_switch");
            return pushFlag;
        }
        if (AbnromalTradeNoticeDescEnum.PriceBreakthroughs_New_High_Monthly == abnromalTradeNoticeDescEnum) {
            pushFlag = getAbnormalPriceSwitch("new_high_monthly_switch");
            return pushFlag;
        }
        if (AbnromalTradeNoticeDescEnum.PriceBreakthroughs_New_Low_Daily == abnromalTradeNoticeDescEnum) {
            pushFlag = getAbnormalPriceSwitch("new_low_daily_switch");
            return pushFlag;
        }
        if (AbnromalTradeNoticeDescEnum.PriceBreakthroughs_New_Low_Weekly == abnromalTradeNoticeDescEnum) {
            pushFlag = getAbnormalPriceSwitch("new_low_weekly_switch");
            return pushFlag;
        }
        if (AbnromalTradeNoticeDescEnum.PriceBreakthroughs_New_Low_Monthly == abnromalTradeNoticeDescEnum) {
            pushFlag = getAbnormalPriceSwitch("new_low_monthly_switch");
            return pushFlag;
        }
        log.info("PriceBreakthroughsServiceImpl.convertPushFlag abnromalTradeNoticeDescEnum={}",
                abnromalTradeNoticeDescEnum);
        return pushFlag;
    }

    /**
     * 获取风控开关配置
     */
    public Boolean getAbnormalPriceSwitch(String displayName) {
        String value = this.sysConfigService.getValue(displayName);
        if (null == value) {
            // 默认开启，就算没有配置开关
            return Boolean.FALSE;
        }
        if ("ON".equals(value)) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }
}
